package we.core.bean;

import java.nio.channels.SocketChannel;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import we.common.CCommonHandler;
import we.config.CConfigHandler;
import we.core.handlers.*;
import we.extension.IExtension;

public class CDataContainer {

    static CDataContainer _instance;
    static final Object lock = new Object();
    Map<String, IExtension> extensions;
    Map<String, CAbstractCoreHandler> coreHandlers;
    Map<String, CUser> usersByName;
    Map<SocketChannel, CUser> usersByChannel;
    Map<Integer, CRoom> roomsById;

    private CDataContainer() {
        initExtensions();
        initCoreHandlers();
        usersByName = new ConcurrentHashMap<String, CUser>();
        usersByChannel = new ConcurrentHashMap<SocketChannel, CUser>();
        roomsById = new ConcurrentHashMap<Integer, CRoom>();
    }

    private void initExtensions() {
        extensions = new HashMap<String, IExtension>();
        String[] extensionList =
                CConfigHandler.instance().get("extensions").split(";");
        for (int i = 0; i < extensionList.length; i++) {
            IExtension ext = null;
            try {
                ext =
                        (IExtension) Class.forName(CConfigHandler.instance().get("extension."
                        + extensionList[i]
                        + ".path")).newInstance();
            } catch (ClassNotFoundException e) {
                CCommonHandler.writeErrLog(e);
            } catch (InstantiationException e) {
                CCommonHandler.writeErrLog(e);
            } catch (IllegalAccessException e) {
                CCommonHandler.writeErrLog(e);
            }
            if (ext != null) {
                ext.init();
                extensions.put(extensionList[i], ext);
            }
        }
    }

    private void initCoreHandlers() {
        coreHandlers = new HashMap<String, CAbstractCoreHandler>();
        coreHandlers.put("login", new CLoginHandler());
        coreHandlers.put("disconnect", new CDisconnectHandler());
        coreHandlers.put("createRoom", new CCreateRoomHandler());
        coreHandlers.put("joinRoom", new CJoinRoomHandler());
        coreHandlers.put("deleteRoom", new CDeleteRoomHandler());
        coreHandlers.put("outRoom", new COutRoomHandler());
    }

    public void addRoom(CRoom r) {
        roomsById.put(r.getRoomId(), r);
    }

    public void removeRoom(CRoom r) {
        roomsById.remove(r.getRoomId());
    }

    public void addUser(CUser u) {
        usersByName.put(u.username, u);
        usersByChannel.put(u.channel, u);
    }

    public void removeUser(CUser u) {
        usersByName.remove(u.username);
        usersByChannel.remove(u.channel);
    }

    public CAbstractCoreHandler getCoreHandler(String command) {
        return coreHandlers.get(command);
    }

    public IExtension getExtension(String name) {
        return extensions.get(name);
    }

    public CUser getUser(String username) {
        return usersByName.get(username);
    }

    public CUser getUserByChannel(SocketChannel channel) {
        return usersByChannel.get(channel);
    }

    public CRoom getRoom(int roomId) {
        return roomsById.get(roomId);
    }

    public Map<String, IExtension> getExtensions() {
        return this.extensions;
    }

    public List<CUser> getUsers() {
        List<CUser> users = new ArrayList<CUser>();
        Iterator it = this.usersByName.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            CUser u = (CUser) entry.getValue();
            users.add(u);
        }
        return users;
    }

    public static CDataContainer instance() {
        if (_instance == null) {
            synchronized (lock) {
                if (_instance == null) {
                    _instance = new CDataContainer();
                }
            }
        }
        return _instance;
    }
}
